#include "Array.hpp"
#include "Debug.hpp"
#include "Solver.hpp"
#include "Types.hpp"
#include <string>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include<stdio.h>
#include <sys/time.h>
#define PI 3.14159265

double timeStamp();

int main(int argc, char *argv[])
{
	if (argc !=3)
	{
		ERROR("Please enter the number of levels and cycles\n ./mgsolve N_levels N_cycles\n Program exiting...\n"); // Valid even if the Debug mode is Off.
		return 1;
	}
	//Parse the parameters
	size_t levels = atoi(argv[1]);
	size_t cycles = atoi(argv[2]);
	//Construct the solver 
	Solver mgSolver=Solver(levels);
	//The dimension of the problem must be equivalent to the one set it up in the solver finest grid. Array(levels-1)
	Array lhs(levels-1);
	Array rhs(levels-1);
	//Initialize the grids
	lhs.fill(0.0);
	rhs.fill(0.0);
	// Boundary conditions
	auto bound_func= [](const real& x,const real& y) ->real {return sin(PI*x)*sinh(PI*y);};
	lhs.setAllDirichletBoundary(bound_func);
	//Solve the problem
	std::cout<<BLUE<<"SOLVING THE PROBLEM ...\n"<<WHITE;
	real t2,t1=timeStamp();
	mgSolver.mgSolve(lhs,rhs,cycles,3,3);
	t2=timeStamp();
	std::cout<<"Computation time(s): "<<t2-t1<<"\n";
	//Printing solution
	//lhs.print(std::cout);
	std::ofstream out("data.dat");
	lhs.printGNUPLOT(out);
	out.close();
	std::cout<<"DONE\n";
	return 0;
}


double timeStamp()
{
  struct timeval tp;
  gettimeofday(&tp, NULL);
  return((double)(tp.tv_sec + tp.tv_usec/1000000.0));
}
